/**
 * pinia v2.0.22
 * (c) 2022 Eduardo San Martin Morote
 * @license MIT
 *
 * @source: https://unpkg.com/pinia@2.0.11/dist/pinia.esm-browser.js
 * @source: https://github.com/vueuse/vue-demi/blob/master/lib/v3/index.cjs
 */

/**
 * Modify list for integration with Bitrix Framework:
 * - remove vue-demi library from global import, replace to 'ui.vue3';
 * - remove import '@vue/devtools-api', add function setupDevtoolsPlugin
 * - replace emoji 'pineapple' to ':Pinia:', replace all emoji to text
 * - added const 'isVue2'
 * - added 'set' and 'del' functions similar to functions from the vue-demi library
 */

import { getCurrentInstance, inject, toRaw, watch, unref, markRaw, effectScope, ref, isRef, isReactive, onUnmounted, reactive, toRef, nextTick, computed, toRefs } from 'ui.vue3';

const isVue2 = false;

function set(object, key, value): any
{
	if (Array.isArray(object))
	{
		object.length = Math.max(object.length, key);
		object.splice(key, 1, value);
	}
	else if (typeof object === 'object')
	{
		object[key] = value;
	}

	return value;
}

function del(object, key): void
{
	if (Array.isArray(object))
	{
		object.splice(key, 1);
	}
	else if (typeof object === 'object')
	{
		delete object[key];
	}
}

function getDevtoolsGlobalHook() {
	return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__;
}
function getTarget() {
	// @ts-ignore
	return typeof navigator !== 'undefined'
		? window
		: typeof global !== 'undefined'
			? global
			: {};
}

const HOOK_SETUP = 'devtools-plugin:setup';

function setupDevtoolsPlugin(pluginDescriptor, setupFn) {
	const hook = getDevtoolsGlobalHook();
	if (hook) {
		hook.emit(HOOK_SETUP, pluginDescriptor, setupFn);
	}
	else {
		const target = getTarget();
		const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || [];
		list.push({
			pluginDescriptor,
			setupFn
		});
	}
}

// origin-start
/**
 * setActivePinia must be called to handle SSR at the top of functions like
 * `fetch`, `setup`, `serverPrefetch` and others
 */
let activePinia;
/**
 * Sets or unsets the active pinia. Used in SSR and internally when calling
 * actions and getters
 *
 * @param pinia - Pinia instance
 */
const setActivePinia = (pinia) => (activePinia = pinia);
/**
 * Get the currently active pinia if there is any.
 */
const getActivePinia = () => (getCurrentInstance() && inject(piniaSymbol)) || activePinia;
const piniaSymbol = (Symbol('pinia') );

function isPlainObject(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
o) {
	return (o &&
		typeof o === 'object' &&
		Object.prototype.toString.call(o) === '[object Object]' &&
		typeof o.toJSON !== 'function');
}
// type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> }
// TODO: can we change these to numbers?
/**
 * Possible types for SubscriptionCallback
 */
var MutationType;
(function (MutationType) {
	/**
	 * Direct mutation of the state:
	 *
	 * - `store.name = 'new name'`
	 * - `store.$state.name = 'new name'`
	 * - `store.list.push('new item')`
	 */
	MutationType["direct"] = "direct";
	/**
	 * Mutated the state with `$patch` and an object
	 *
	 * - `store.$patch({ name: 'newName' })`
	 */
	MutationType["patchObject"] = "patch object";
	/**
	 * Mutated the state with `$patch` and a function
	 *
	 * - `store.$patch(state => state.name = 'newName')`
	 */
	MutationType["patchFunction"] = "patch function";
	// maybe reset? for $state = {} and $reset
})(MutationType || (MutationType = {}));

const IS_CLIENT = typeof window !== 'undefined';
/**
 * Should we add the devtools plugins.
 * - only if dev mode or forced through the prod devtools flag
 * - not in test
 * - only if window exists (could change in the future)
 */
const USE_DEVTOOLS = IS_CLIENT;

/*
 * FileSaver.js A saveAs() FileSaver implementation.
 *
 * Originally by Eli Grey, adapted as an ESM module by Eduardo San Martin
 * Morote.
 *
 * License : MIT
 */
// The one and only way of getting global scope in all environments
// https://stackoverflow.com/q/3277182/1008999
const _global = /*#__PURE__*/ (() => typeof window === 'object' && window.window === window
	? window
	: typeof self === 'object' && self.self === self
		? self
		: typeof global === 'object' && global.global === global
			? global
			: typeof globalThis === 'object'
				? globalThis
				: { HTMLElement: null })();
function bom(blob, { autoBom = false } = {}) {
	// prepend BOM for UTF-8 XML and text/* types (including HTML)
	// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
	if (autoBom &&
		/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
		return new Blob([String.fromCharCode(0xfeff), blob], { type: blob.type });
	}
	return blob;
}
function download(url, name, opts) {
	const xhr = new XMLHttpRequest();
	xhr.open('GET', url);
	xhr.responseType = 'blob';
	xhr.onload = function () {
		saveAs(xhr.response, name, opts);
	};
	xhr.onerror = function () {
		console.error('could not download file');
	};
	xhr.send();
}
function corsEnabled(url) {
	const xhr = new XMLHttpRequest();
	// use sync to avoid popup blocker
	xhr.open('HEAD', url, false);
	try {
		xhr.send();
	}
	catch (e) { }
	return xhr.status >= 200 && xhr.status <= 299;
}
// `a.click()` doesn't work for all browsers (#465)
function click(node) {
	try {
		node.dispatchEvent(new MouseEvent('click'));
	}
	catch (e) {
		const evt = document.createEvent('MouseEvents');
		evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
		node.dispatchEvent(evt);
	}
}
const _navigator =
	typeof navigator === 'object' ? navigator : { userAgent: '' };
// Detect WebView inside a native macOS app by ruling out all browsers
// We just need to check for 'Safari' because all other browsers (besides Firefox) include that too
// https://www.whatismybrowser.com/guides/the-latest-user-agent/macos
const isMacOSWebView = /*#__PURE__*/ (() => /Macintosh/.test(_navigator.userAgent) &&
	/AppleWebKit/.test(_navigator.userAgent) &&
	!/Safari/.test(_navigator.userAgent))();
const saveAs = !IS_CLIENT
	? () => { } // noop
	: // Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView or mini program
	typeof HTMLAnchorElement !== 'undefined' &&
	'download' in HTMLAnchorElement.prototype &&
	!isMacOSWebView
		? downloadSaveAs
		: // Use msSaveOrOpenBlob as a second approach
		'msSaveOrOpenBlob' in _navigator
			? msSaveAs
			: // Fallback to using FileReader and a popup
			fileSaverSaveAs;
function downloadSaveAs(blob, name = 'download', opts) {
	const a = document.createElement('a');
	a.download = name;
	a.rel = 'noopener'; // tabnabbing
	// TODO: detect chrome extensions & packaged apps
	// a.target = '_blank'
	if (typeof blob === 'string') {
		// Support regular links
		a.href = blob;
		if (a.origin !== location.origin) {
			if (corsEnabled(a.href)) {
				download(blob, name, opts);
			}
			else {
				a.target = '_blank';
				click(a);
			}
		}
		else {
			click(a);
		}
	}
	else {
		// Support blobs
		a.href = URL.createObjectURL(blob);
		setTimeout(function () {
			URL.revokeObjectURL(a.href);
		}, 4e4); // 40s
		setTimeout(function () {
			click(a);
		}, 0);
	}
}
function msSaveAs(blob, name = 'download', opts) {
	if (typeof blob === 'string') {
		if (corsEnabled(blob)) {
			download(blob, name, opts);
		}
		else {
			const a = document.createElement('a');
			a.href = blob;
			a.target = '_blank';
			setTimeout(function () {
				click(a);
			});
		}
	}
	else {
		// @ts-ignore: works on windows
		navigator.msSaveOrOpenBlob(bom(blob, opts), name);
	}
}
function fileSaverSaveAs(blob, name, opts, popup) {
	// Open a popup immediately do go around popup blocker
	// Mostly only available on user interaction and the fileReader is async so...
	popup = popup || open('', '_blank');
	if (popup) {
		popup.document.title = popup.document.body.innerText = 'downloading...';
	}
	if (typeof blob === 'string')
		return download(blob, name, opts);
	const force = blob.type === 'application/octet-stream';
	const isSafari = /constructor/i.test(String(_global.HTMLElement)) || 'safari' in _global;
	const isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
	if ((isChromeIOS || (force && isSafari) || isMacOSWebView) &&
		typeof FileReader !== 'undefined') {
		// Safari doesn't allow downloading of blob URLs
		const reader = new FileReader();
		reader.onloadend = function () {
			let url = reader.result;
			if (typeof url !== 'string') {
				popup = null;
				throw new Error('Wrong reader.result type');
			}
			url = isChromeIOS
				? url
				: url.replace(/^data:[^;]*;/, 'data:attachment/file;');
			if (popup) {
				popup.location.href = url;
			}
			else {
				location.assign(url);
			}
			popup = null; // reverse-tabnabbing #460
		};
		reader.readAsDataURL(blob);
	}
	else {
		const url = URL.createObjectURL(blob);
		if (popup)
			popup.location.assign(url);
		else
			location.href = url;
		popup = null; // reverse-tabnabbing #460
		setTimeout(function () {
			URL.revokeObjectURL(url);
		}, 4e4); // 40s
	}
}

/**
 * Shows a toast or console.log
 *
 * @param message - message to log
 * @param type - different color of the tooltip
 */
function toastMessage(message, type) {
	const piniaMessage = 'Pinia: ' + message;
	if (typeof __VUE_DEVTOOLS_TOAST__ === 'function') {
		__VUE_DEVTOOLS_TOAST__(piniaMessage, type);
	}
	else if (type === 'error') {
		console.error(piniaMessage);
	}
	else if (type === 'warn') {
		console.warn(piniaMessage);
	}
	else {
		console.log(piniaMessage);
	}
}
function isPinia(o) {
	return '_a' in o && 'install' in o;
}

function checkClipboardAccess() {
	if (!('clipboard' in navigator)) {
		toastMessage(`Your browser doesn't support the Clipboard API`, 'error');
		return true;
	}
}
function checkNotFocusedError(error) {
	if (error instanceof Error &&
		error.message.toLowerCase().includes('document is not focused')) {
		toastMessage('You need to activate the "Emulate a focused page" setting in the "Rendering" panel of devtools.', 'warn');
		return true;
	}
	return false;
}
async function actionGlobalCopyState(pinia) {
	if (checkClipboardAccess())
		return;
	try {
		await navigator.clipboard.writeText(JSON.stringify(pinia.state.value));
		toastMessage('Global state copied to clipboard.');
	}
	catch (error) {
		if (checkNotFocusedError(error))
			return;
		toastMessage(`Failed to serialize the state. Check the console for more details.`, 'error');
		console.error(error);
	}
}
async function actionGlobalPasteState(pinia) {
	if (checkClipboardAccess())
		return;
	try {
		pinia.state.value = JSON.parse(await navigator.clipboard.readText());
		toastMessage('Global state pasted from clipboard.');
	}
	catch (error) {
		if (checkNotFocusedError(error))
			return;
		toastMessage(`Failed to deserialize the state from clipboard. Check the console for more details.`, 'error');
		console.error(error);
	}
}
async function actionGlobalSaveState(pinia) {
	try {
		saveAs(new Blob([JSON.stringify(pinia.state.value)], {
			type: 'text/plain;charset=utf-8',
		}), 'pinia-state.json');
	}
	catch (error) {
		toastMessage(`Failed to export the state as JSON. Check the console for more details.`, 'error');
		console.error(error);
	}
}
let fileInput;
function getFileOpener() {
	if (!fileInput) {
		fileInput = document.createElement('input');
		fileInput.type = 'file';
		fileInput.accept = '.json';
	}
	function openFile() {
		return new Promise((resolve, reject) => {
			fileInput.onchange = async () => {
				const files = fileInput.files;
				if (!files)
					return resolve(null);
				const file = files.item(0);
				if (!file)
					return resolve(null);
				return resolve({ text: await file.text(), file });
			};
			// @ts-ignore: TODO: changed from 4.3 to 4.4
			fileInput.oncancel = () => resolve(null);
			fileInput.onerror = reject;
			fileInput.click();
		});
	}
	return openFile;
}
async function actionGlobalOpenStateFile(pinia) {
	try {
		const open = await getFileOpener();
		const result = await open();
		if (!result)
			return;
		const { text, file } = result;
		pinia.state.value = JSON.parse(text);
		toastMessage(`Global state imported from "${file.name}".`);
	}
	catch (error) {
		toastMessage(`Failed to export the state as JSON. Check the console for more details.`, 'error');
		console.error(error);
	}
}

function formatDisplay(display) {
	return {
		_custom: {
			display,
		},
	};
}
const PINIA_ROOT_LABEL = 'Pinia (root)';
const PINIA_ROOT_ID = '_root';
function formatStoreForInspectorTree(store) {
	return isPinia(store)
		? {
			id: PINIA_ROOT_ID,
			label: PINIA_ROOT_LABEL,
		}
		: {
			id: store.$id,
			label: store.$id,
		};
}
function formatStoreForInspectorState(store) {
	if (isPinia(store)) {
		const storeNames = Array.from(store._s.keys());
		const storeMap = store._s;
		const state = {
			state: storeNames.map((storeId) => ({
				editable: true,
				key: storeId,
				value: store.state.value[storeId],
			})),
			getters: storeNames
				.filter((id) => storeMap.get(id)._getters)
				.map((id) => {
					const store = storeMap.get(id);
					return {
						editable: false,
						key: id,
						value: store._getters.reduce((getters, key) => {
							getters[key] = store[key];
							return getters;
						}, {}),
					};
				}),
		};
		return state;
	}
	const state = {
		state: Object.keys(store.$state).map((key) => ({
			editable: true,
			key,
			value: store.$state[key],
		})),
	};
	// avoid adding empty getters
	if (store._getters && store._getters.length) {
		state.getters = store._getters.map((getterName) => ({
			editable: false,
			key: getterName,
			value: store[getterName],
		}));
	}
	if (store._customProperties.size) {
		state.customProperties = Array.from(store._customProperties).map((key) => ({
			editable: true,
			key,
			value: store[key],
		}));
	}
	return state;
}
function formatEventData(events) {
	if (!events)
		return {};
	if (Array.isArray(events)) {
		// TODO: handle add and delete for arrays and objects
		return events.reduce((data, event) => {
			data.keys.push(event.key);
			data.operations.push(event.type);
			data.oldValue[event.key] = event.oldValue;
			data.newValue[event.key] = event.newValue;
			return data;
		}, {
			oldValue: {},
			keys: [],
			operations: [],
			newValue: {},
		});
	}
	else {
		return {
			operation: formatDisplay(events.type),
			key: formatDisplay(events.key),
			oldValue: events.oldValue,
			newValue: events.newValue,
		};
	}
}
function formatMutationType(type) {
	switch (type) {
		case MutationType.direct:
			return 'mutation';
		case MutationType.patchFunction:
			return '$patch';
		case MutationType.patchObject:
			return '$patch';
		default:
			return 'unknown';
	}
}

// timeline can be paused when directly changing the state
let isTimelineActive = true;
const componentStateTypes = [];
const MUTATIONS_LAYER_ID = 'pinia:mutations';
const INSPECTOR_ID = 'pinia';
/**
 * Gets the displayed name of a store in devtools
 *
 * @param id - id of the store
 * @returns a formatted string
 */
const getStoreType = (id) => ':Pinia: ' + id;
/**
 * Add the pinia plugin without any store. Allows displaying a Pinia plugin tab
 * as soon as it is added to the application.
 *
 * @param app - Vue application
 * @param pinia - pinia instance
 */
function registerPiniaDevtools(app, pinia) {
	setupDevtoolsPlugin({
		id: 'dev.esm.pinia',
		label: 'Pinia',
		logo: 'https://pinia.vuejs.org/logo.svg',
		packageName: 'pinia',
		homepage: 'https://pinia.vuejs.org',
		componentStateTypes,
		app,
	}, (api) => {
		if (typeof api.now !== 'function') {
			toastMessage('You seem to be using an outdated version of Vue Devtools. Are you still using the Beta release instead of the stable one? You can find the links at https://devtools.vuejs.org/guide/installation.html.');
		}
		api.addTimelineLayer({
			id: MUTATIONS_LAYER_ID,
			label: `Pinia`,
			color: 0xe5df88,
		});
		api.addInspector({
			id: INSPECTOR_ID,
			label: 'Pinia',
			icon: 'storage',
			treeFilterPlaceholder: 'Search stores',
			actions: [
				{
					icon: 'content_copy',
					action: () => {
						actionGlobalCopyState(pinia);
					},
					tooltip: 'Serialize and copy the state',
				},
				{
					icon: 'content_paste',
					action: async () => {
						await actionGlobalPasteState(pinia);
						api.sendInspectorTree(INSPECTOR_ID);
						api.sendInspectorState(INSPECTOR_ID);
					},
					tooltip: 'Replace the state with the content of your clipboard',
				},
				{
					icon: 'save',
					action: () => {
						actionGlobalSaveState(pinia);
					},
					tooltip: 'Save the state as a JSON file',
				},
				{
					icon: 'folder_open',
					action: async () => {
						await actionGlobalOpenStateFile(pinia);
						api.sendInspectorTree(INSPECTOR_ID);
						api.sendInspectorState(INSPECTOR_ID);
					},
					tooltip: 'Import the state from a JSON file',
				},
			],
			nodeActions: [
				{
					icon: 'restore',
					tooltip: 'Reset the state (option store only)',
					action: (nodeId) => {
						const store = pinia._s.get(nodeId);
						if (!store) {
							toastMessage(`Cannot reset "${nodeId}" store because it wasn't found.`, 'warn');
						}
						else if (!store._isOptionsAPI) {
							toastMessage(`Cannot reset "${nodeId}" store because it's a setup store.`, 'warn');
						}
						else {
							store.$reset();
							toastMessage(`Store "${nodeId}" reset.`);
						}
					},
				},
			],
		});
		api.on.inspectComponent((payload, ctx) => {
			const proxy = (payload.componentInstance &&
				payload.componentInstance.proxy);
			if (proxy && proxy._pStores) {
				const piniaStores = payload.componentInstance.proxy._pStores;
				Object.values(piniaStores).forEach((store) => {
					payload.instanceData.state.push({
						type: getStoreType(store.$id),
						key: 'state',
						editable: true,
						value: store._isOptionsAPI
							? {
								_custom: {
									value: toRaw(store.$state),
									actions: [
										{
											icon: 'restore',
											tooltip: 'Reset the state of this store',
											action: () => store.$reset(),
										},
									],
								},
							}
							: // NOTE: workaround to unwrap transferred refs
							Object.keys(store.$state).reduce((state, key) => {
								state[key] = store.$state[key];
								return state;
							}, {}),
					});
					if (store._getters && store._getters.length) {
						payload.instanceData.state.push({
							type: getStoreType(store.$id),
							key: 'getters',
							editable: false,
							value: store._getters.reduce((getters, key) => {
								try {
									getters[key] = store[key];
								}
								catch (error) {
									// @ts-expect-error: we just want to show it in devtools
									getters[key] = error;
								}
								return getters;
							}, {}),
						});
					}
				});
			}
		});
		api.on.getInspectorTree((payload) => {
			if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
				let stores = [pinia];
				stores = stores.concat(Array.from(pinia._s.values()));
				payload.rootNodes = (payload.filter
					? stores.filter((store) => '$id' in store
						? store.$id
							.toLowerCase()
							.includes(payload.filter.toLowerCase())
						: PINIA_ROOT_LABEL.toLowerCase().includes(payload.filter.toLowerCase()))
					: stores).map(formatStoreForInspectorTree);
			}
		});
		api.on.getInspectorState((payload) => {
			if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
				const inspectedStore = payload.nodeId === PINIA_ROOT_ID
					? pinia
					: pinia._s.get(payload.nodeId);
				if (!inspectedStore) {
					// this could be the selected store restored for a different project
					// so it's better not to say anything here
					return;
				}
				if (inspectedStore) {
					payload.state = formatStoreForInspectorState(inspectedStore);
				}
			}
		});
		api.on.editInspectorState((payload, ctx) => {
			if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
				const inspectedStore = payload.nodeId === PINIA_ROOT_ID
					? pinia
					: pinia._s.get(payload.nodeId);
				if (!inspectedStore) {
					return toastMessage(`store "${payload.nodeId}" not found`, 'error');
				}
				const { path } = payload;
				if (!isPinia(inspectedStore)) {
					// access only the state
					if (path.length !== 1 ||
						!inspectedStore._customProperties.has(path[0]) ||
						path[0] in inspectedStore.$state) {
						path.unshift('$state');
					}
				}
				else {
					// Root access, we can omit the `.value` because the devtools API does it for us
					path.unshift('state');
				}
				isTimelineActive = false;
				payload.set(inspectedStore, path, payload.state.value);
				isTimelineActive = true;
			}
		});
		api.on.editComponentState((payload) => {
			if (payload.type.startsWith(':Pinia:')) {
				const storeId = payload.type.replace(/^:Pinia:\s*/, '');
				const store = pinia._s.get(storeId);
				if (!store) {
					return toastMessage(`store "${storeId}" not found`, 'error');
				}
				const { path } = payload;
				if (path[0] !== 'state') {
					return toastMessage(`Invalid path for store "${storeId}":\n${path}\nOnly state can be modified.`);
				}
				// rewrite the first entry to be able to directly set the state as
				// well as any other path
				path[0] = '$state';
				isTimelineActive = false;
				payload.set(store, path, payload.state.value);
				isTimelineActive = true;
			}
		});
	});
}
function addStoreToDevtools(app, store) {
	if (!componentStateTypes.includes(getStoreType(store.$id))) {
		componentStateTypes.push(getStoreType(store.$id));
	}
	setupDevtoolsPlugin({
		id: 'dev.esm.pinia',
		label: 'Pinia',
		logo: 'https://pinia.vuejs.org/logo.svg',
		packageName: 'pinia',
		homepage: 'https://pinia.vuejs.org',
		componentStateTypes,
		app,
		settings: {
			logStoreChanges: {
				label: 'Notify about new/deleted stores',
				type: 'boolean',
				defaultValue: true,
			},
			// useEmojis: {
			//   label: 'Use emojis in messages',
			//   type: 'boolean',
			//   defaultValue: true,
			// },
		},
	}, (api) => {
		// gracefully handle errors
		const now = typeof api.now === 'function' ? api.now.bind(api) : Date.now;
		store.$onAction(({ after, onError, name, args }) => {
			const groupId = runningActionId++;
			api.addTimelineEvent({
				layerId: MUTATIONS_LAYER_ID,
				event: {
					time: now(),
					title: 'Start ' + name,
					subtitle: 'start',
					data: {
						store: formatDisplay(store.$id),
						action: formatDisplay(name),
						args,
					},
					groupId,
				},
			});
			after((result) => {
				activeAction = undefined;
				api.addTimelineEvent({
					layerId: MUTATIONS_LAYER_ID,
					event: {
						time: now(),
						title: 'End ' + name,
						subtitle: 'end',
						data: {
							store: formatDisplay(store.$id),
							action: formatDisplay(name),
							args,
							result,
						},
						groupId,
					},
				});
			});
			onError((error) => {
				activeAction = undefined;
				api.addTimelineEvent({
					layerId: MUTATIONS_LAYER_ID,
					event: {
						time: now(),
						logType: 'error',
						title: 'Error ' + name,
						subtitle: 'end',
						data: {
							store: formatDisplay(store.$id),
							action: formatDisplay(name),
							args,
							error,
						},
						groupId,
					},
				});
			});
		}, true);
		store._customProperties.forEach((name) => {
			watch(() => unref(store[name]), (newValue, oldValue) => {
				api.notifyComponentUpdate();
				api.sendInspectorState(INSPECTOR_ID);
				if (isTimelineActive) {
					api.addTimelineEvent({
						layerId: MUTATIONS_LAYER_ID,
						event: {
							time: now(),
							title: 'Change',
							subtitle: name,
							data: {
								newValue,
								oldValue,
							},
							groupId: activeAction,
						},
					});
				}
			}, { deep: true });
		});
		store.$subscribe(({ events, type }, state) => {
			api.notifyComponentUpdate();
			api.sendInspectorState(INSPECTOR_ID);
			if (!isTimelineActive)
				return;
			// rootStore.state[store.id] = state
			const eventData = {
				time: now(),
				title: formatMutationType(type),
				data: {
					store: formatDisplay(store.$id),
					...formatEventData(events),
				},
				groupId: activeAction,
			};
			// reset for the next mutation
			activeAction = undefined;
			if (type === MutationType.patchFunction) {
				eventData.subtitle = 'Down';
			}
			else if (type === MutationType.patchObject) {
				eventData.subtitle = 'Patch';
			}
			else if (events && !Array.isArray(events)) {
				eventData.subtitle = events.type;
			}
			if (events) {
				eventData.data['rawEvent(s)'] = {
					_custom: {
						display: 'DebuggerEvent',
						type: 'object',
						tooltip: 'raw DebuggerEvent[]',
						value: events,
					},
				};
			}
			api.addTimelineEvent({
				layerId: MUTATIONS_LAYER_ID,
				event: eventData,
			});
		}, { detached: true, flush: 'sync' });
		const hotUpdate = store._hotUpdate;
		store._hotUpdate = markRaw((newStore) => {
			hotUpdate(newStore);
			api.addTimelineEvent({
				layerId: MUTATIONS_LAYER_ID,
				event: {
					time: now(),
					title: 'Hot update ' + store.$id,
					subtitle: 'HMR update',
					data: {
						store: formatDisplay(store.$id),
						info: formatDisplay(`HMR update`),
					},
				},
			});
			// update the devtools too
			api.notifyComponentUpdate();
			api.sendInspectorTree(INSPECTOR_ID);
			api.sendInspectorState(INSPECTOR_ID);
		});
		const { $dispose } = store;
		store.$dispose = () => {
			$dispose();
			api.notifyComponentUpdate();
			api.sendInspectorTree(INSPECTOR_ID);
			api.sendInspectorState(INSPECTOR_ID);
			api.getSettings().logStoreChanges &&
			toastMessage(`Disposed "${store.$id}" store`);
		};
		// trigger an update so it can display new registered stores
		api.notifyComponentUpdate();
		api.sendInspectorTree(INSPECTOR_ID);
		api.sendInspectorState(INSPECTOR_ID);
		api.getSettings().logStoreChanges &&
		toastMessage(`"${store.$id}" store installed`);
	});
}
let runningActionId = 0;
let activeAction;
/**
 * Patches a store to enable action grouping in devtools by wrapping the store with a Proxy that is passed as the
 * context of all actions, allowing us to set `runningAction` on each access and effectively associating any state
 * mutation to the action.
 *
 * @param store - store to patch
 * @param actionNames - list of actionst to patch
 */
function patchActionForGrouping(store, actionNames) {
	// original actions of the store as they are given by pinia. We are going to override them
	const actions = actionNames.reduce((storeActions, actionName) => {
		// use toRaw to avoid tracking #541
		storeActions[actionName] = toRaw(store)[actionName];
		return storeActions;
	}, {});
	for (const actionName in actions) {
		store[actionName] = function () {
			// setActivePinia(store._p)
			// the running action id is incremented in a before action hook
			const _actionId = runningActionId;
			const trackedStore = new Proxy(store, {
				get(...args) {
					activeAction = _actionId;
					return Reflect.get(...args);
				},
				set(...args) {
					activeAction = _actionId;
					return Reflect.set(...args);
				},
			});
			return actions[actionName].apply(trackedStore, arguments);
		};
	}
}
/**
 * pinia.use(devtoolsPlugin)
 */
function devtoolsPlugin({ app, store, options }) {
	// HMR module
	if (store.$id.startsWith('__hot:')) {
		return;
	}
	// detect option api vs setup api
	if (options.state) {
		store._isOptionsAPI = true;
	}
	// only wrap actions in option-defined stores as this technique relies on
	// wrapping the context of the action with a proxy
	if (typeof options.state === 'function') {
		patchActionForGrouping(
			// @ts-expect-error: can cast the store...
			store, Object.keys(options.actions));
		const originalHotUpdate = store._hotUpdate;
		// Upgrade the HMR to also update the new actions
		toRaw(store)._hotUpdate = function (newStore) {
			originalHotUpdate.apply(this, arguments);
			patchActionForGrouping(store, Object.keys(newStore._hmrPayload.actions));
		};
	}
	addStoreToDevtools(app,
		// FIXME: is there a way to allow the assignment from Store<Id, S, G, A> to StoreGeneric?
		store);
}

/**
 * Creates a Pinia instance to be used by the application
 */
function createPinia() {
	const scope = effectScope(true);
	// NOTE: here we could check the window object for a state and directly set it
	// if there is anything like it with Vue 3 SSR
	const state = scope.run(() => ref({}));
	let _p = [];
	// plugins added before calling app.use(pinia)
	let toBeInstalled = [];
	const pinia = markRaw({
		install(app) {
			// this allows calling useStore() outside of a component setup after
			// installing pinia's plugin
			setActivePinia(pinia);
			if (!isVue2) {
				pinia._a = app;
				app.provide(piniaSymbol, pinia);
				app.config.globalProperties.$pinia = pinia;
				/* istanbul ignore else */
				if (USE_DEVTOOLS) {
					registerPiniaDevtools(app, pinia);
				}
				toBeInstalled.forEach((plugin) => _p.push(plugin));
				toBeInstalled = [];
			}
		},
		use(plugin) {
			if (!this._a && !isVue2) {
				toBeInstalled.push(plugin);
			}
			else {
				_p.push(plugin);
			}
			return this;
		},
		_p,
		// it's actually undefined here
		// @ts-expect-error
		_a: null,
		_e: scope,
		_s: new Map(),
		state,
	});
	// pinia devtools rely on dev only features so they cannot be forced unless
	// the dev build of Vue is used. Avoid old browsers like IE11.
	if (USE_DEVTOOLS && typeof Proxy !== 'undefined') {
		pinia.use(devtoolsPlugin);
	}
	return pinia;
}

/**
 * Checks if a function is a `StoreDefinition`.
 *
 * @param fn - object to test
 * @returns true if `fn` is a StoreDefinition
 */
const isUseStore = (fn) => {
	return typeof fn === 'function' && typeof fn.$id === 'string';
};
/**
 * Mutates in place `newState` with `oldState` to _hot update_ it. It will
 * remove any key not existing in `newState` and recursively merge plain
 * objects.
 *
 * @param newState - new state object to be patched
 * @param oldState - old state that should be used to patch newState
 * @returns - newState
 */
function patchObject(newState, oldState) {
	// no need to go through symbols because they cannot be serialized anyway
	for (const key in oldState) {
		const subPatch = oldState[key];
		// skip the whole sub tree
		if (!(key in newState)) {
			continue;
		}
		const targetValue = newState[key];
		if (isPlainObject(targetValue) &&
			isPlainObject(subPatch) &&
			!isRef(subPatch) &&
			!isReactive(subPatch)) {
			newState[key] = patchObject(targetValue, subPatch);
		}
		else {
			// objects are either a bit more complex (e.g. refs) or primitives, so we
			// just set the whole thing
			if (isVue2) {
				set(newState, key, subPatch);
			}
			else {
				newState[key] = subPatch;
			}
		}
	}
	return newState;
}
/**
 * Creates an _accept_ function to pass to `import.meta.hot` in Vite applications.
 *
 * @example
 * ```js
 * const useUser = defineStore(...)
 * if (import.meta.hot) {
 *   import.meta.hot.accept(acceptHMRUpdate(useUser, import.meta.hot))
 * }
 * ```
 *
 * @param initialUseStore - return of the defineStore to hot update
 * @param hot - `import.meta.hot`
 */
function acceptHMRUpdate(initialUseStore, hot) {
	return (newModule) => {
		const pinia = hot.data.pinia || initialUseStore._pinia;
		if (!pinia) {
			// this store is still not used
			return;
		}
		// preserve the pinia instance across loads
		hot.data.pinia = pinia;
		// console.log('got data', newStore)
		for (const exportName in newModule) {
			const useStore = newModule[exportName];
			// console.log('checking for', exportName)
			if (isUseStore(useStore) && pinia._s.has(useStore.$id)) {
				// console.log('Accepting update for', useStore.$id)
				const id = useStore.$id;
				if (id !== initialUseStore.$id) {
					console.warn(`The id of the store changed from "${initialUseStore.$id}" to "${id}". Reloading.`);
					// return import.meta.hot.invalidate()
					return hot.invalidate();
				}
				const existingStore = pinia._s.get(id);
				if (!existingStore) {
					console.log(`[Pinia]: skipping hmr because store doesn't exist yet`);
					return;
				}
				useStore(pinia, existingStore);
			}
		}
	};
}

const noop = () => { };
function addSubscription(subscriptions, callback, detached, onCleanup = noop) {
	subscriptions.push(callback);
	const removeSubscription = () => {
		const idx = subscriptions.indexOf(callback);
		if (idx > -1) {
			subscriptions.splice(idx, 1);
			onCleanup();
		}
	};
	if (!detached && getCurrentInstance()) {
		onUnmounted(removeSubscription);
	}
	return removeSubscription;
}
function triggerSubscriptions(subscriptions, ...args) {
	subscriptions.slice().forEach((callback) => {
		callback(...args);
	});
}

function mergeReactiveObjects(target, patchToApply) {
	// Handle Map instances
	if (target instanceof Map && patchToApply instanceof Map) {
		patchToApply.forEach((value, key) => target.set(key, value));
	}
	// Handle Set instances
	if (target instanceof Set && patchToApply instanceof Set) {
		patchToApply.forEach(target.add, target);
	}
	// no need to go through symbols because they cannot be serialized anyway
	for (const key in patchToApply) {
		if (!patchToApply.hasOwnProperty(key))
			continue;
		const subPatch = patchToApply[key];
		const targetValue = target[key];
		if (isPlainObject(targetValue) &&
			isPlainObject(subPatch) &&
			target.hasOwnProperty(key) &&
			!isRef(subPatch) &&
			!isReactive(subPatch)) {
			// NOTE: here I wanted to warn about inconsistent types but it's not possible because in setup stores one might
			// start the value of a property as a certain type e.g. a Map, and then for some reason, during SSR, change that
			// to `undefined`. When trying to hydrate, we want to override the Map with `undefined`.
			target[key] = mergeReactiveObjects(targetValue, subPatch);
		}
		else {
			// @ts-expect-error: subPatch is a valid value
			target[key] = subPatch;
		}
	}
	return target;
}
const skipHydrateSymbol = Symbol('pinia:skipHydration')
;
const skipHydrateMap = /*#__PURE__*/ new WeakMap();
/**
 * Tells Pinia to skip the hydration process of a given object. This is useful in setup stores (only) when you return a
 * stateful object in the store but it isn't really state. e.g. returning a router instance in a setup store.
 *
 * @param obj - target object
 * @returns obj
 */
function skipHydrate(obj) {
	return isVue2
		? // in @vue/composition-api, the refs are sealed so defineProperty doesn't work...
		/* istanbul ignore next */ skipHydrateMap.set(obj, 1) && obj
		: Object.defineProperty(obj, skipHydrateSymbol, {});
}
function shouldHydrate(obj) {
	return isVue2
		? /* istanbul ignore next */ !skipHydrateMap.has(obj)
		: !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol);
}
const { assign } = Object;
function isComputed(o) {
	return !!(isRef(o) && o.effect);
}
function createOptionsStore(id, options, pinia, hot) {
	const { state, actions, getters } = options;
	const initialState = pinia.state.value[id];
	let store;
	function setup() {
		if (!initialState && (!hot)) {
			/* istanbul ignore if */
			if (isVue2) {
				set(pinia.state.value, id, state ? state() : {});
			}
			else {
				pinia.state.value[id] = state ? state() : {};
			}
		}
		// avoid creating a state in pinia.state.value
		const localState = hot
			? // use ref() to unwrap refs inside state TODO: check if this is still necessary
			toRefs(ref(state ? state() : {}).value)
			: toRefs(pinia.state.value[id]);
		return assign(localState, actions, Object.keys(getters || {}).reduce((computedGetters, name) => {
			if (name in localState) {
				console.warn(`[Pinia]: A getter cannot have the same name as another state property. Rename one of them. Found with "${name}" in store "${id}".`);
			}
			computedGetters[name] = markRaw(computed(() => {
				setActivePinia(pinia);
				// it was created just before
				const store = pinia._s.get(id);
				// allow cross using stores
				/* istanbul ignore next */
				if (isVue2 && !store._r)
					return;
				// @ts-expect-error
				// return getters![name].call(context, context)
				// TODO: avoid reading the getter while assigning with a global variable
				return getters[name].call(store, store);
			}));
			return computedGetters;
		}, {}));
	}
	store = createSetupStore(id, setup, options, pinia, hot, true);
	store.$reset = function $reset() {
		const newState = state ? state() : {};
		// we use a patch to group all changes into one single subscription
		this.$patch(($state) => {
			assign($state, newState);
		});
	};
	return store;
}
function createSetupStore($id, setup, options = {}, pinia, hot, isOptionsStore) {
	let scope;
	const optionsForPlugin = assign({ actions: {} }, options);
	/* istanbul ignore if */
	// @ts-expect-error: active is an internal property
	if (!pinia._e.active) {
		throw new Error('Pinia destroyed');
	}
	// watcher options for $subscribe
	const $subscribeOptions = {
		deep: true,
		// flush: 'post',
	};
	/* istanbul ignore else */
	if (!isVue2) {
		$subscribeOptions.onTrigger = (event) => {
			/* istanbul ignore else */
			if (isListening) {
				debuggerEvents = event;
				// avoid triggering this while the store is being built and the state is being set in pinia
			}
			else if (isListening == false && !store._hotUpdating) {
				// let patch send all the events together later
				/* istanbul ignore else */
				if (Array.isArray(debuggerEvents)) {
					debuggerEvents.push(event);
				}
				else {
					console.error('Pinia: debuggerEvents should be an array. This is most likely an internal Pinia bug.');
				}
			}
		};
	}
	// internal state
	let isListening; // set to true at the end
	let isSyncListening; // set to true at the end
	let subscriptions = markRaw([]);
	let actionSubscriptions = markRaw([]);
	let debuggerEvents;
	const initialState = pinia.state.value[$id];
	// avoid setting the state for option stores if it is set
	// by the setup
	if (!isOptionsStore && !initialState && (!hot)) {
		/* istanbul ignore if */
		if (isVue2) {
			set(pinia.state.value, $id, {});
		}
		else {
			pinia.state.value[$id] = {};
		}
	}
	const hotState = ref({});
	// avoid triggering too many listeners
	// https://github.com/vuejs/pinia/issues/1129
	let activeListener;
	function $patch(partialStateOrMutator) {
		let subscriptionMutation;
		isListening = isSyncListening = false;
		// reset the debugger events since patches are sync
		/* istanbul ignore else */
		{
			debuggerEvents = [];
		}
		if (typeof partialStateOrMutator === 'function') {
			partialStateOrMutator(pinia.state.value[$id]);
			subscriptionMutation = {
				type: MutationType.patchFunction,
				storeId: $id,
				events: debuggerEvents,
			};
		}
		else {
			mergeReactiveObjects(pinia.state.value[$id], partialStateOrMutator);
			subscriptionMutation = {
				type: MutationType.patchObject,
				payload: partialStateOrMutator,
				storeId: $id,
				events: debuggerEvents,
			};
		}
		const myListenerId = (activeListener = Symbol());
		nextTick().then(() => {
			if (activeListener === myListenerId) {
				isListening = true;
			}
		});
		isSyncListening = true;
		// because we paused the watcher, we need to manually call the subscriptions
		triggerSubscriptions(subscriptions, subscriptionMutation, pinia.state.value[$id]);
	}
	/* istanbul ignore next */
	const $reset = () => {
			throw new Error(`Pinia: Store "${$id}" is built using the setup syntax and does not implement $reset().`);
		}
	;
	function $dispose() {
		scope.stop();
		subscriptions = [];
		actionSubscriptions = [];
		pinia._s.delete($id);
	}
	/**
	 * Wraps an action to handle subscriptions.
	 *
	 * @param name - name of the action
	 * @param action - action to wrap
	 * @returns a wrapped action to handle subscriptions
	 */
	function wrapAction(name, action) {
		return function () {
			setActivePinia(pinia);
			const args = Array.from(arguments);
			const afterCallbackList = [];
			const onErrorCallbackList = [];
			function after(callback) {
				afterCallbackList.push(callback);
			}
			function onError(callback) {
				onErrorCallbackList.push(callback);
			}
			// @ts-expect-error
			triggerSubscriptions(actionSubscriptions, {
				args,
				name,
				store,
				after,
				onError,
			});
			let ret;
			try {
				ret = action.apply(this && this.$id === $id ? this : store, args);
				// handle sync errors
			}
			catch (error) {
				triggerSubscriptions(onErrorCallbackList, error);
				throw error;
			}
			if (ret instanceof Promise) {
				return ret
					.then((value) => {
						triggerSubscriptions(afterCallbackList, value);
						return value;
					})
					.catch((error) => {
						triggerSubscriptions(onErrorCallbackList, error);
						return Promise.reject(error);
					});
			}
			// allow the afterCallback to override the return value
			triggerSubscriptions(afterCallbackList, ret);
			return ret;
		};
	}
	const _hmrPayload = /*#__PURE__*/ markRaw({
		actions: {},
		getters: {},
		state: [],
		hotState,
	});
	const partialStore = {
		_p: pinia,
		// _s: scope,
		$id,
		$onAction: addSubscription.bind(null, actionSubscriptions),
		$patch,
		$reset,
		$subscribe(callback, options = {}) {
			const removeSubscription = addSubscription(subscriptions, callback, options.detached, () => stopWatcher());
			const stopWatcher = scope.run(() => watch(() => pinia.state.value[$id], (state) => {
				if (options.flush === 'sync' ? isSyncListening : isListening) {
					callback({
						storeId: $id,
						type: MutationType.direct,
						events: debuggerEvents,
					}, state);
				}
			}, assign({}, $subscribeOptions, options)));
			return removeSubscription;
		},
		$dispose,
	};
	/* istanbul ignore if */
	if (isVue2) {
		// start as non ready
		partialStore._r = false;
	}
	const store = reactive(assign(IS_CLIENT
			? // devtools custom properties
			{
				_customProperties: markRaw(new Set()),
				_hmrPayload,
			}
			: {}, partialStore
		// must be added later
		// setupStore
	));
	// store the partial store now so the setup of stores can instantiate each other before they are finished without
	// creating infinite loops.
	pinia._s.set($id, store);
	// TODO: idea create skipSerialize that marks properties as non serializable and they are skipped
	const setupStore = pinia._e.run(() => {
		scope = effectScope();
		return scope.run(() => setup());
	});
	// overwrite existing actions to support $onAction
	for (const key in setupStore) {
		const prop = setupStore[key];
		if ((isRef(prop) && !isComputed(prop)) || isReactive(prop)) {
			// mark it as a piece of state to be serialized
			if (hot) {
				set(hotState.value, key, toRef(setupStore, key));
				// createOptionStore directly sets the state in pinia.state.value so we
				// can just skip that
			}
			else if (!isOptionsStore) {
				// in setup stores we must hydrate the state and sync pinia state tree with the refs the user just created
				if (initialState && shouldHydrate(prop)) {
					if (isRef(prop)) {
						prop.value = initialState[key];
					}
					else {
						// probably a reactive object, lets recursively assign
						mergeReactiveObjects(prop, initialState[key]);
					}
				}
				// transfer the ref to the pinia state to keep everything in sync
				/* istanbul ignore if */
				if (isVue2) {
					set(pinia.state.value[$id], key, prop);
				}
				else {
					pinia.state.value[$id][key] = prop;
				}
			}
			/* istanbul ignore else */
			{
				_hmrPayload.state.push(key);
			}
			// action
		}
		else if (typeof prop === 'function') {
			// @ts-expect-error: we are overriding the function we avoid wrapping if
			const actionValue = hot ? prop : wrapAction(key, prop);
			// this a hot module replacement store because the hotUpdate method needs
			// to do it with the right context
			/* istanbul ignore if */
			if (isVue2) {
				set(setupStore, key, actionValue);
			}
			else {
				// @ts-expect-error
				setupStore[key] = actionValue;
			}
			/* istanbul ignore else */
			{
				_hmrPayload.actions[key] = prop;
			}
			// list actions so they can be used in plugins
			// @ts-expect-error
			optionsForPlugin.actions[key] = prop;
		}
		else {
			// add getters for devtools
			if (isComputed(prop)) {
				_hmrPayload.getters[key] = isOptionsStore
					? // @ts-expect-error
					options.getters[key]
					: prop;
				if (IS_CLIENT) {
					const getters =
						// @ts-expect-error: it should be on the store
						setupStore._getters || (setupStore._getters = markRaw([]));
					getters.push(key);
				}
			}
		}
	}
	// add the state, getters, and action properties
	/* istanbul ignore if */
	if (isVue2) {
		Object.keys(setupStore).forEach((key) => {
			set(store, key,
				// @ts-expect-error: valid key indexing
				setupStore[key]);
		});
	}
	else {
		assign(store, setupStore);
		// allows retrieving reactive objects with `storeToRefs()`. Must be called after assigning to the reactive object.
		// Make `storeToRefs()` work with `reactive()` #799
		assign(toRaw(store), setupStore);
	}
	// use this instead of a computed with setter to be able to create it anywhere
	// without linking the computed lifespan to wherever the store is first
	// created.
	Object.defineProperty(store, '$state', {
		get: () => (hot ? hotState.value : pinia.state.value[$id]),
		set: (state) => {
			/* istanbul ignore if */
			if (hot) {
				throw new Error('cannot set hotState');
			}
			$patch(($state) => {
				assign($state, state);
			});
		},
	});
	// add the hotUpdate before plugins to allow them to override it
	/* istanbul ignore else */
	{
		store._hotUpdate = markRaw((newStore) => {
			store._hotUpdating = true;
			newStore._hmrPayload.state.forEach((stateKey) => {
				if (stateKey in store.$state) {
					const newStateTarget = newStore.$state[stateKey];
					const oldStateSource = store.$state[stateKey];
					if (typeof newStateTarget === 'object' &&
						isPlainObject(newStateTarget) &&
						isPlainObject(oldStateSource)) {
						patchObject(newStateTarget, oldStateSource);
					}
					else {
						// transfer the ref
						newStore.$state[stateKey] = oldStateSource;
					}
				}
				// patch direct access properties to allow store.stateProperty to work as
				// store.$state.stateProperty
				set(store, stateKey, toRef(newStore.$state, stateKey));
			});
			// remove deleted state properties
			Object.keys(store.$state).forEach((stateKey) => {
				if (!(stateKey in newStore.$state)) {
					del(store, stateKey);
				}
			});
			// avoid devtools logging this as a mutation
			isListening = false;
			isSyncListening = false;
			pinia.state.value[$id] = toRef(newStore._hmrPayload, 'hotState');
			isSyncListening = true;
			nextTick().then(() => {
				isListening = true;
			});
			for (const actionName in newStore._hmrPayload.actions) {
				const action = newStore[actionName];
				set(store, actionName, wrapAction(actionName, action));
			}
			// TODO: does this work in both setup and option store?
			for (const getterName in newStore._hmrPayload.getters) {
				const getter = newStore._hmrPayload.getters[getterName];
				const getterValue = isOptionsStore
					? // special handling of options api
					computed(() => {
						setActivePinia(pinia);
						return getter.call(store, store);
					})
					: getter;
				set(store, getterName, getterValue);
			}
			// remove deleted getters
			Object.keys(store._hmrPayload.getters).forEach((key) => {
				if (!(key in newStore._hmrPayload.getters)) {
					del(store, key);
				}
			});
			// remove old actions
			Object.keys(store._hmrPayload.actions).forEach((key) => {
				if (!(key in newStore._hmrPayload.actions)) {
					del(store, key);
				}
			});
			// update the values used in devtools and to allow deleting new properties later on
			store._hmrPayload = newStore._hmrPayload;
			store._getters = newStore._getters;
			store._hotUpdating = false;
		});
		const nonEnumerable = {
			writable: true,
			configurable: true,
			// avoid warning on devtools trying to display this property
			enumerable: false,
		};
		if (IS_CLIENT) {
			['_p', '_hmrPayload', '_getters', '_customProperties'].forEach((p) => {
				Object.defineProperty(store, p, {
					value: store[p],
					...nonEnumerable,
				});
			});
		}
	}
	/* istanbul ignore if */
	if (isVue2) {
		// mark the store as ready before plugins
		store._r = true;
	}
	// apply all plugins
	pinia._p.forEach((extender) => {
		/* istanbul ignore else */
		if (IS_CLIENT) {
			const extensions = scope.run(() => extender({
				store,
				app: pinia._a,
				pinia,
				options: optionsForPlugin,
			}));
			Object.keys(extensions || {}).forEach((key) => store._customProperties.add(key));
			assign(store, extensions);
		}
		else {
			assign(store, scope.run(() => extender({
				store,
				app: pinia._a,
				pinia,
				options: optionsForPlugin,
			})));
		}
	});
	if (store.$state &&
		typeof store.$state === 'object' &&
		typeof store.$state.constructor === 'function' &&
		!store.$state.constructor.toString().includes('[native code]')) {
		console.warn(`[Pinia]: The "state" must be a plain object. It cannot be\n` +
			`\tstate: () => new MyClass()\n` +
			`Found in store "${store.$id}".`);
	}
	// only apply hydrate to option stores with an initial state in pinia
	if (initialState &&
		isOptionsStore &&
		options.hydrate) {
		options.hydrate(store.$state, initialState);
	}
	isListening = true;
	isSyncListening = true;
	return store;
}
function defineStore(
// TODO: add proper types from above
idOrOptions, setup, setupOptions) {
	let id;
	let options;
	const isSetupStore = typeof setup === 'function';
	if (typeof idOrOptions === 'string') {
		id = idOrOptions;
		// the option store setup will contain the actual options in this case
		options = isSetupStore ? setupOptions : setup;
	}
	else {
		options = idOrOptions;
		id = idOrOptions.id;
	}
	function useStore(pinia, hot) {
		const currentInstance = getCurrentInstance();
		pinia =
			// in test mode, ignore the argument provided as we can always retrieve a
			// pinia instance with getActivePinia()
			(pinia) ||
			(currentInstance && inject(piniaSymbol));
		if (pinia)
			setActivePinia(pinia);
		if (!activePinia) {
			throw new Error(`[Pinia]: getActivePinia was called with no active Pinia. Did you forget to install pinia?\n` +
				`\tconst pinia = createPinia()\n` +
				`\tapp.use(pinia)\n` +
				`This will fail in production.`);
		}
		pinia = activePinia;
		if (!pinia._s.has(id)) {
			// creating the store registers it in `pinia._s`
			if (isSetupStore) {
				createSetupStore(id, setup, options, pinia);
			}
			else {
				createOptionsStore(id, options, pinia);
			}
			/* istanbul ignore else */
			{
				// @ts-expect-error: not the right inferred type
				useStore._pinia = pinia;
			}
		}
		const store = pinia._s.get(id);
		if (hot) {
			const hotId = '__hot:' + id;
			const newStore = isSetupStore
				? createSetupStore(hotId, setup, options, pinia, true)
				: createOptionsStore(hotId, assign({}, options), pinia, true);
			hot._hotUpdate(newStore);
			// cleanup the state properties and the store from the cache
			delete pinia.state.value[hotId];
			pinia._s.delete(hotId);
		}
		// save stores in instances to access them devtools
		if (IS_CLIENT &&
			currentInstance &&
			currentInstance.proxy &&
			// avoid adding stores that are just built for hot module replacement
			!hot) {
			const vm = currentInstance.proxy;
			const cache = '_pStores' in vm ? vm._pStores : (vm._pStores = {});
			cache[id] = store;
		}
		// StoreGeneric cannot be casted towards Store
		return store;
	}
	useStore.$id = id;
	return useStore;
}

let mapStoreSuffix = 'Store';
/**
 * Changes the suffix added by `mapStores()`. Can be set to an empty string.
 * Defaults to `"Store"`. Make sure to extend the MapStoresCustomization
 * interface if you are using TypeScript.
 *
 * @param suffix - new suffix
 */
function setMapStoreSuffix(suffix // could be 'Store' but that would be annoying for JS
) {
	mapStoreSuffix = suffix;
}
/**
 * Allows using stores without the composition API (`setup()`) by generating an
 * object to be spread in the `computed` field of a component. It accepts a list
 * of store definitions.
 *
 * @example
 * ```js
 * export default {
 *   computed: {
 *     // other computed properties
 *     ...mapStores(useUserStore, useCartStore)
 *   },
 *
 *   created() {
 *     this.userStore // store with id "user"
 *     this.cartStore // store with id "cart"
 *   }
 * }
 * ```
 *
 * @param stores - list of stores to map to an object
 */
function mapStores(...stores) {
	if (Array.isArray(stores[0])) {
		console.warn(`[Pinia]: Directly pass all stores to "mapStores()" without putting them in an array:\n` +
			`Replace\n` +
			`\tmapStores([useAuthStore, useCartStore])\n` +
			`with\n` +
			`\tmapStores(useAuthStore, useCartStore)\n` +
			`This will fail in production if not fixed.`);
		stores = stores[0];
	}
	return stores.reduce((reduced, useStore) => {
		// @ts-expect-error: $id is added by defineStore
		reduced[useStore.$id + mapStoreSuffix] = function () {
			return useStore(this.$pinia);
		};
		return reduced;
	}, {});
}
/**
 * Allows using state and getters from one store without using the composition
 * API (`setup()`) by generating an object to be spread in the `computed` field
 * of a component.
 *
 * @param useStore - store to map from
 * @param keysOrMapper - array or object
 */
function mapState(useStore, keysOrMapper) {
	return Array.isArray(keysOrMapper)
		? keysOrMapper.reduce((reduced, key) => {
			reduced[key] = function () {
				return useStore(this.$pinia)[key];
			};
			return reduced;
		}, {})
		: Object.keys(keysOrMapper).reduce((reduced, key) => {
			// @ts-expect-error
			reduced[key] = function () {
				const store = useStore(this.$pinia);
				const storeKey = keysOrMapper[key];
				// for some reason TS is unable to infer the type of storeKey to be a
				// function
				return typeof storeKey === 'function'
					? storeKey.call(this, store)
					: store[storeKey];
			};
			return reduced;
		}, {});
}
/**
 * Alias for `mapState()`. You should use `mapState()` instead.
 * @deprecated use `mapState()` instead.
 */
const mapGetters = mapState;
/**
 * Allows directly using actions from your store without using the composition
 * API (`setup()`) by generating an object to be spread in the `methods` field
 * of a component.
 *
 * @param useStore - store to map from
 * @param keysOrMapper - array or object
 */
function mapActions(useStore, keysOrMapper) {
	return Array.isArray(keysOrMapper)
		? keysOrMapper.reduce((reduced, key) => {
			// @ts-expect-error
			reduced[key] = function (...args) {
				return useStore(this.$pinia)[key](...args);
			};
			return reduced;
		}, {})
		: Object.keys(keysOrMapper).reduce((reduced, key) => {
			// @ts-expect-error
			reduced[key] = function (...args) {
				return useStore(this.$pinia)[keysOrMapper[key]](...args);
			};
			return reduced;
		}, {});
}
/**
 * Allows using state and getters from one store without using the composition
 * API (`setup()`) by generating an object to be spread in the `computed` field
 * of a component.
 *
 * @param useStore - store to map from
 * @param keysOrMapper - array or object
 */
function mapWritableState(useStore, keysOrMapper) {
	return Array.isArray(keysOrMapper)
		? keysOrMapper.reduce((reduced, key) => {
			// @ts-ignore
			reduced[key] = {
				get() {
					return useStore(this.$pinia)[key];
				},
				set(value) {
					// it's easier to type it here as any
					return (useStore(this.$pinia)[key] = value);
				},
			};
			return reduced;
		}, {})
		: Object.keys(keysOrMapper).reduce((reduced, key) => {
			// @ts-ignore
			reduced[key] = {
				get() {
					return useStore(this.$pinia)[keysOrMapper[key]];
				},
				set(value) {
					// it's easier to type it here as any
					return (useStore(this.$pinia)[keysOrMapper[key]] = value);
				},
			};
			return reduced;
		}, {});
}

/**
 * Creates an object of references with all the state, getters, and plugin-added
 * state properties of the store. Similar to `toRefs()` but specifically
 * designed for Pinia stores so methods and non reactive properties are
 * completely ignored.
 *
 * @param store - store to extract the refs from
 */
function storeToRefs(store) {
	// See https://github.com/vuejs/pinia/issues/852
	// It's easier to just use toRefs() even if it includes more stuff
	if (isVue2) {
		// @ts-expect-error: toRefs include methods and others
		return toRefs(store);
	}
	else {
		store = toRaw(store);
		const refs = {};
		for (const key in store) {
			const value = store[key];
			if (isRef(value) || isReactive(value)) {
				// @ts-expect-error: the key is state or getter
				refs[key] =
					// ---
					toRef(store, key);
			}
		}
		return refs;
	}
}

/**
 * Vue 2 Plugin that must be installed for pinia to work. Note **you don't need
 * this plugin if you are using Nuxt.js**. Use the `buildModule` instead:
 * https://pinia.vuejs.org/ssr/nuxt.html.
 *
 * @example
 * ```js
 * import Vue from 'vue'
 * import { PiniaVuePlugin, createPinia } from 'pinia'
 *
 * Vue.use(PiniaVuePlugin)
 * const pinia = createPinia()
 *
 * new Vue({
 *   el: '#app',
 *   // ...
 *   pinia,
 * })
 * ```
 *
 * @param _Vue - `Vue` imported from 'vue'.
 */
const PiniaVuePlugin = function (_Vue) {
	// Equivalent of
	// app.config.globalProperties.$pinia = pinia
	_Vue.mixin({
		beforeCreate() {
			const options = this.$options;
			if (options.pinia) {
				const pinia = options.pinia;
				// HACK: taken from provide(): https://github.com/vuejs/composition-api/blob/main/src/apis/inject.ts#L31
				/* istanbul ignore else */
				if (!this._provided) {
					const provideCache = {};
					Object.defineProperty(this, '_provided', {
						get: () => provideCache,
						set: (v) => Object.assign(provideCache, v),
					});
				}
				this._provided[piniaSymbol] = pinia;
				// propagate the pinia instance in an SSR friendly way
				// avoid adding it to nuxt twice
				/* istanbul ignore else */
				if (!this.$pinia) {
					this.$pinia = pinia;
				}
				pinia._a = this;
				if (IS_CLIENT) {
					// this allows calling useStore() outside of a component setup after
					// installing pinia's plugin
					setActivePinia(pinia);
				}
				if (USE_DEVTOOLS) {
					registerPiniaDevtools(pinia._a, pinia);
				}
			}
			else if (!this.$pinia && options.parent && options.parent.$pinia) {
				this.$pinia = options.parent.$pinia;
			}
		},
		destroyed() {
			delete this._pStores;
		},
	});
};

export { MutationType, PiniaVuePlugin, acceptHMRUpdate, createPinia, defineStore, getActivePinia, mapActions, mapGetters, mapState, mapStores, mapWritableState, setActivePinia, setMapStoreSuffix, skipHydrate, storeToRefs };
// origin-end
const version = '2.0.22';
export {version}